#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Git 代码行数统计工具
统计指定 Git 仓库中当前用户提交的代码行数（排除注释）
区分前端代码和后端代码
"""

import os
import re
import sys
from collections import defaultdict
from typing import Dict, Set, Tuple
import git
from colorama import init, Fore, Style
from report_generator import HTMLReportGenerator

# 初始化 colorama（Windows 支持）
init(autoreset=True)


class GitCounter:
    """Git 代码统计器"""
    
    # 前端文件扩展名
    FRONTEND_EXTENSIONS = {
        '.html', '.htm', '.css', '.scss', '.sass', '.less',
        '.js', '.jsx', '.ts', '.tsx', '.vue', '.svelte',
        '.json', '.xml', '.yaml', '.yml'
    }
    
    # 后端文件扩展名
    BACKEND_EXTENSIONS = {
        '.py', '.java', '.go', '.rb', '.php', '.c', '.cpp', '.cc',
        '.h', '.hpp', '.cs', '.rs', '.kt', '.scala', '.swift',
        '.sql', '.sh', '.bash', '.ps1'
    }
    
    # 单行注释规则（按文件扩展名）
    SINGLE_LINE_COMMENT = {
        '.py': r'^\s*#',
        '.js': r'^\s*//',
        '.jsx': r'^\s*//',
        '.ts': r'^\s*//',
        '.tsx': r'^\s*//',
        '.java': r'^\s*//',
        '.c': r'^\s*//',
        '.cpp': r'^\s*//',
        '.cc': r'^\s*//',
        '.h': r'^\s*//',
        '.hpp': r'^\s*//',
        '.cs': r'^\s*//',
        '.go': r'^\s*//',
        '.php': r'^\s*(//#)',
        '.rb': r'^\s*#',
        '.sh': r'^\s*#',
        '.bash': r'^\s*#',
        '.sql': r'^\s*--',
        '.html': r'^\s*<!--',
        '.xml': r'^\s*<!--',
        '.css': r'^\s*/\*',
        '.scss': r'^\s*//',
        '.sass': r'^\s*//',
        '.less': r'^\s*//',
    }
    
    # 多行注释规则（开始和结束标记）
    MULTI_LINE_COMMENT = {
        '.py': (r'^\s*"""', r'"""'),
        '.js': (r'^\s*/\*', r'\*/'),
        '.jsx': (r'^\s*/\*', r'\*/'),
        '.ts': (r'^\s*/\*', r'\*/'),
        '.tsx': (r'^\s*/\*', r'\*/'),
        '.java': (r'^\s*/\*', r'\*/'),
        '.c': (r'^\s*/\*', r'\*/'),
        '.cpp': (r'^\s*/\*', r'\*/'),
        '.cc': (r'^\s*/\*', r'\*/'),
        '.h': (r'^\s*/\*', r'\*/'),
        '.hpp': (r'^\s*/\*', r'\*/'),
        '.cs': (r'^\s*/\*', r'\*/'),
        '.go': (r'^\s*/\*', r'\*/'),
        '.php': (r'^\s*/\*', r'\*/'),
        '.css': (r'^\s*/\*', r'\*/'),
        '.scss': (r'^\s*/\*', r'\*/'),
        '.less': (r'^\s*/\*', r'\*/'),
        '.html': (r'^\s*<!--', r'-->'),
        '.xml': (r'^\s*<!--', r'-->'),
    }
    
    def __init__(self, repo_path: str):
        """
        初始化 Git 统计器
        
        Args:
            repo_path: Git 仓库路径
        """
        self.repo_path = os.path.abspath(repo_path)
        
        try:
            self.repo = git.Repo(self.repo_path)
        except git.exc.InvalidGitRepositoryError:
            raise ValueError(f"错误：'{repo_path}' 不是一个有效的 Git 仓库")
        except Exception as e:
            raise ValueError(f"错误：无法打开 Git 仓库：{e}")
        
        # 只读取仓库本地配置，不读取全局配置
        self.git_user_name = None
        self.git_user_email = None
        
        try:
            # 只从本地配置读取
            with self.repo.config_reader() as config:
                try:
                    self.git_user_name = config.get_value("user", "name", default=None)
                except Exception:
                    self.git_user_name = None
                
                try:
                    self.git_user_email = config.get_value("user", "email", default=None)
                except Exception:
                    self.git_user_email = None
            
            # 至少需要用户名或邮箱其中之一
            if not self.git_user_name and not self.git_user_email:
                raise ValueError("未检测到本地 Git 用户配置")
        except Exception as e:
            raise ValueError(f"错误：无法获取本地 Git 用户配置：{e}\n请在仓库目录执行: git config user.name \"your_name\"")
        
        # 统计数据
        self.stats = {
            'frontend': {'added': 0, 'deleted': 0, 'total': 0, 'current': 0},
            'backend': {'added': 0, 'deleted': 0, 'total': 0, 'current': 0},
            'other': {'added': 0, 'deleted': 0, 'total': 0, 'current': 0},
        }
        
        self.file_stats = defaultdict(lambda: {'added': 0, 'deleted': 0, 'current': 0})
        
        # 当前代码量统计（基于 git blame）
        self.current_stats_available = False
    
    def is_comment_line(self, line: str, file_ext: str, in_multi_comment: bool) -> Tuple[bool, bool]:
        """
        判断是否为注释行
        
        Args:
            line: 代码行
            file_ext: 文件扩展名
            in_multi_comment: 当前是否在多行注释中
        
        Returns:
            (是否为注释, 是否在多行注释中)
        """
        stripped = line.strip()
        
        # 空行不算注释
        if not stripped:
            return False, in_multi_comment
        
        # 检查多行注释
        if file_ext in self.MULTI_LINE_COMMENT:
            start_pattern, end_pattern = self.MULTI_LINE_COMMENT[file_ext]
            
            # 检查是否开始多行注释
            if re.match(start_pattern, stripped):
                in_multi_comment = True
                # 检查是否在同一行结束
                if re.search(end_pattern, stripped):
                    in_multi_comment = False
                return True, in_multi_comment
            
            # 检查是否结束多行注释
            if in_multi_comment:
                if re.search(end_pattern, stripped):
                    in_multi_comment = False
                return True, in_multi_comment
        
        # 如果在多行注释中
        if in_multi_comment:
            return True, in_multi_comment
        
        # 检查单行注释
        if file_ext in self.SINGLE_LINE_COMMENT:
            pattern = self.SINGLE_LINE_COMMENT[file_ext]
            if re.match(pattern, stripped):
                return True, in_multi_comment
        
        return False, in_multi_comment
    
    def classify_file(self, file_path: str) -> str:
        """
        分类文件类型
        
        Args:
            file_path: 文件路径
        
        Returns:
            'frontend', 'backend', 或 'other'
        """
        _, ext = os.path.splitext(file_path.lower())
        
        if ext in self.FRONTEND_EXTENSIONS:
            return 'frontend'
        elif ext in self.BACKEND_EXTENSIONS:
            return 'backend'
        else:
            return 'other'
    
    def count_diff_lines(self, diff_text: str, file_ext: str) -> Tuple[int, int]:
        """
        统计 diff 中的新增和删除行数（排除注释）
        
        Args:
            diff_text: Git diff 文本
            file_ext: 文件扩展名
        
        Returns:
            (新增行数, 删除行数)
        """
        added = 0
        deleted = 0
        in_multi_comment = False
        
        for line in diff_text.split('\n'):
            if not line:
                continue
            
            # 跳过 diff 元数据行
            if line.startswith('@@') or line.startswith('diff --git') or \
               line.startswith('index ') or line.startswith('---') or \
               line.startswith('+++'):
                continue
            
            # 新增行
            if line.startswith('+'):
                code_line = line[1:]  # 去掉 + 号
                is_comment, in_multi_comment = self.is_comment_line(code_line, file_ext, in_multi_comment)
                if not is_comment and code_line.strip():  # 排除注释和空行
                    added += 1
            
            # 删除行
            elif line.startswith('-'):
                code_line = line[1:]  # 去掉 - 号
                is_comment, in_multi_comment = self.is_comment_line(code_line, file_ext, in_multi_comment)
                if not is_comment and code_line.strip():  # 排除注释和空行
                    deleted += 1
        
        return added, deleted
    
    def analyze_commit(self, commit):
        """
        分析单个提交
        
        Args:
            commit: Git commit 对象
        """
        # 跳过合并提交（Merge Commit）
        if len(commit.parents) > 1:
            return
        
        # 检查是否为当前用户的提交（支持只匹配用户名或邮箱）
        is_match = False
        
        if self.git_user_name and self.git_user_email:
            # 两者都有，任一匹配即可
            is_match = (commit.author.name == self.git_user_name or 
                       commit.author.email == self.git_user_email)
        elif self.git_user_name:
            # 只有用户名，按用户名匹配
            is_match = (commit.author.name == self.git_user_name)
        elif self.git_user_email:
            # 只有邮箱，按邮箱匹配
            is_match = (commit.author.email == self.git_user_email)
        
        if not is_match:
            return
        
        # 获取父提交
        if not commit.parents:
            # 首次提交，与空树比较
            parent = None
        else:
            parent = commit.parents[0]
        
        # 获取 diff
        try:
            if parent:
                diffs = parent.diff(commit, create_patch=True)
            else:
                # 首次提交
                diffs = commit.diff(git.NULL_TREE, create_patch=True)
        except Exception:
            return
        
        # 分析每个文件的变更
        for diff_item in diffs:
            # 获取文件路径
            file_path = diff_item.b_path if diff_item.b_path else diff_item.a_path
            if not file_path:
                continue
            
            # 判断文件变更类型
            is_new_file = diff_item.new_file
            is_deleted_file = diff_item.deleted_file
            is_renamed_file = diff_item.renamed_file
            
            # 分类文件
            file_type = self.classify_file(file_path)
            
            # 获取文件扩展名
            _, file_ext = os.path.splitext(file_path.lower())
            
            # 获取 diff 文本
            try:
                if diff_item.diff:
                    diff_text = diff_item.diff.decode('utf-8', errors='ignore')
                else:
                    continue
            except Exception:
                continue
            
            # 统计行数
            added, deleted = self.count_diff_lines(diff_text, file_ext)
            
            # 计算工作量（智能算法）
            if is_new_file:
                # 新建文件：净增量
                workload = added - deleted
            elif is_deleted_file:
                # 删除文件：不算工作量
                workload = 0
            elif is_renamed_file:
                # 重命名文件：按新建处理
                workload = added - deleted
            else:
                # 修改文件：新增×0.9 + 删除×0.1
                workload = int(added * 0.9 + deleted * 0.1)
            
            # 更新统计
            self.stats[file_type]['added'] += added
            self.stats[file_type]['deleted'] += deleted
            self.stats[file_type]['total'] += workload
            
            # 更新文件统计
            self.file_stats[file_path]['added'] += added
            self.file_stats[file_path]['deleted'] += deleted
    
    def analyze_current_code(self):
        """
        分析当前代码量（基于 git blame）
        统计当前工作区中属于当前用户的代码行数
        """
        print(f"\n{Fore.CYAN}正在分析当前代码量（使用 git blame）...")
        
        try:
            # 获取所有被 Git 跟踪的文件
            tracked_files = []
            try:
                # 使用 git ls-files 获取所有跟踪的文件
                git_cmd = self.repo.git
                files_output = git_cmd.execute(['git', 'ls-files'])
                tracked_files = [f.strip() for f in files_output.split('\n') if f.strip()]
            except Exception as e:
                print(f"{Fore.RED}获取文件列表失败：{e}")
                return False
            
            if not tracked_files:
                print(f"{Fore.YELLOW}没有找到被跟踪的文件")
                return False
            
            total_files = len(tracked_files)
            print(f"{Fore.YELLOW}共找到 {total_files} 个文件，正在分析...")
            
            processed = 0
            for file_path in tracked_files:
                processed += 1
                if processed % 10 == 0 or processed == total_files:
                    print(f"{Fore.YELLOW}进度：{processed}/{total_files} ({processed*100//total_files}%)", end='\r')
                
                # 获取文件扩展名和类型
                _, file_ext = os.path.splitext(file_path.lower())
                file_type = self.classify_file(file_path)
                
                # 获取文件的完整路径
                full_path = os.path.join(self.repo_path, file_path)
                
                # 检查文件是否存在（可能已被删除）
                if not os.path.exists(full_path):
                    continue
                
                # 使用 git blame 分析文件
                try:
                    # 执行 git blame
                    blame_output = git_cmd.blame('-e', '--line-porcelain', file_path)
                    
                    # 解析 blame 输出，统计当前用户的代码行
                    user_lines = 0
                    in_multi_comment = False
                    
                    lines = blame_output.split('\n')
                    i = 0
                    while i < len(lines):
                        line = lines[i]
                        
                        # blame 输出格式：每个代码块以 commit hash 开始
                        if line and not line.startswith('\t'):
                            # 查找 author 和 author-mail 行
                            author_name = None
                            author_mail = None
                            j = i
                            while j < len(lines) and not lines[j].startswith('\t'):
                                if lines[j].startswith('author '):
                                    author_name = lines[j][7:].strip()
                                elif lines[j].startswith('author-mail '):
                                    author_mail = lines[j][12:].strip()
                                j += 1
                            
                            # 查找实际的代码行（以 \t 开头）
                            while j < len(lines) and not lines[j].startswith('\t'):
                                j += 1
                            
                            if j < len(lines):
                                code_line = lines[j][1:]  # 去掉开头的 \t
                                
                                # 灵活匹配当前用户（支持只有用户名或只有邮箱）
                                is_current_user = False
                                
                                if self.git_user_name and self.git_user_email:
                                    # 两者都有，任一匹配即可
                                    is_current_user = (
                                        (author_name and author_name == self.git_user_name) or
                                        (author_mail and (f'<{self.git_user_email}>' in author_mail or self.git_user_email in author_mail))
                                    )
                                elif self.git_user_name:
                                    # 只有用户名，按用户名匹配
                                    is_current_user = (author_name and author_name == self.git_user_name)
                                elif self.git_user_email:
                                    # 只有邮箱，按邮箱匹配
                                    is_current_user = (author_mail and (f'<{self.git_user_email}>' in author_mail or self.git_user_email in author_mail))
                                
                                if is_current_user:
                                    # 检查是否是注释或空行
                                    is_comment, in_multi_comment = self.is_comment_line(
                                        code_line, file_ext, in_multi_comment
                                    )
                                    
                                    if not is_comment and code_line.strip():
                                        user_lines += 1
                            
                            i = j + 1
                        else:
                            i += 1
                    
                    # 更新统计
                    if user_lines > 0:
                        self.stats[file_type]['current'] += user_lines
                        self.file_stats[file_path]['current'] = user_lines
                
                except Exception as e:
                    # 某些文件可能无法 blame（如二进制文件）
                    continue
            
            print(f"\n{Fore.GREEN}当前代码量分析完成！\n")
            self.current_stats_available = True
            return True
            
        except Exception as e:
            print(f"{Fore.RED}当前代码量分析失败：{e}")
            return False
    
    def analyze(self, include_current_stats: bool = True):
        """
        执行分析
        
        Args:
            include_current_stats: 是否包含当前代码量统计（默认True）
        """
        print(f"\n{Fore.CYAN}正在分析 Git 仓库：{self.repo_path}")
        print(f"{Fore.CYAN}统计用户：{self.git_user_name} <{self.git_user_email}>")
        print(f"{Fore.CYAN}当前分支：{self.repo.active_branch.name}\n")
        
        # 获取所有提交
        commits = list(self.repo.iter_commits(self.repo.active_branch.name))
        total_commits = len(commits)
        
        print(f"{Fore.YELLOW}共有 {total_commits} 个提交，正在分析历史变更...")
        
        # 分析每个提交
        for i, commit in enumerate(commits, 1):
            if i % 10 == 0 or i == total_commits:
                print(f"{Fore.YELLOW}进度：{i}/{total_commits}", end='\r')
            
            self.analyze_commit(commit)
        
        print(f"\n{Fore.GREEN}历史变更分析完成！\n")
        
        # 分析当前代码量
        if include_current_stats:
            self.analyze_current_code()
    
    def print_report(self):
        """打印统计报告"""
        print(f"{Fore.CYAN}{'=' * 70}")
        print(f"{Fore.CYAN}{'代码统计报告':^66}")
        print(f"{Fore.CYAN}{'=' * 70}\n")
        
        # 格式化用户信息显示
        if self.git_user_name and self.git_user_email:
            user_display = f"{self.git_user_name} <{self.git_user_email}>"
        elif self.git_user_name:
            user_display = f"{self.git_user_name}"
        else:
            user_display = f"<{self.git_user_email}>"
        
        print(f"{Fore.WHITE}用户：{Style.BRIGHT}{user_display}")
        print(f"{Fore.WHITE}仓库：{Style.BRIGHT}{self.repo_path}")
        print(f"{Fore.WHITE}分支：{Style.BRIGHT}{self.repo.active_branch.name}\n")
        
        # 说明文字
        print(f"{Fore.YELLOW}{'统计说明':^66}")
        print(f"{Fore.YELLOW}{'-' * 70}")
        print(f"{Fore.WHITE}  📊 累计工作量：统计所有历史提交的代码变更（包括后来修改/删除的）")
        if self.current_stats_available:
            print(f"{Fore.WHITE}  📝 当前代码量：统计当前代码库中属于你的有效代码行数")
        print()
        
        # 前端统计
        frontend = self.stats['frontend']
        print(f"{Fore.GREEN}{'前端代码统计':^66}")
        print(f"{Fore.GREEN}{'-' * 70}")
        print(f"  【累计工作量】")
        print(f"    新增行数：{Fore.GREEN}{Style.BRIGHT}{frontend['added']:>10,}")
        print(f"    删除行数：{Fore.RED}{Style.BRIGHT}{frontend['deleted']:>10,}")
        print(f"    净增行数：{Fore.CYAN}{Style.BRIGHT}{frontend['total']:>10,}")
        if self.current_stats_available:
            print(f"  【当前代码量】")
            print(f"    当前拥有：{Fore.MAGENTA}{Style.BRIGHT}{frontend['current']:>10,} 行")
        print()
        
        # 后端统计
        backend = self.stats['backend']
        print(f"{Fore.BLUE}{'后端代码统计':^66}")
        print(f"{Fore.BLUE}{'-' * 70}")
        print(f"  【累计工作量】")
        print(f"    新增行数：{Fore.GREEN}{Style.BRIGHT}{backend['added']:>10,}")
        print(f"    删除行数：{Fore.RED}{Style.BRIGHT}{backend['deleted']:>10,}")
        print(f"    净增行数：{Fore.CYAN}{Style.BRIGHT}{backend['total']:>10,}")
        if self.current_stats_available:
            print(f"  【当前代码量】")
            print(f"    当前拥有：{Fore.MAGENTA}{Style.BRIGHT}{backend['current']:>10,} 行")
        print()
        
        # 其他文件统计
        other = self.stats['other']
        if other['added'] > 0 or other['deleted'] > 0 or (self.current_stats_available and other['current'] > 0):
            print(f"{Fore.YELLOW}{'其他文件统计':^66}")
            print(f"{Fore.YELLOW}{'-' * 70}")
            print(f"  【累计工作量】")
            print(f"    新增行数：{Fore.GREEN}{Style.BRIGHT}{other['added']:>10,}")
            print(f"    删除行数：{Fore.RED}{Style.BRIGHT}{other['deleted']:>10,}")
            print(f"    净增行数：{Fore.CYAN}{Style.BRIGHT}{other['total']:>10,}")
            if self.current_stats_available:
                print(f"  【当前代码量】")
                print(f"    当前拥有：{Fore.MAGENTA}{Style.BRIGHT}{other['current']:>10,} 行")
            print()
        
        # 总计
        total_added = frontend['added'] + backend['added'] + other['added']
        total_deleted = frontend['deleted'] + backend['deleted'] + other['deleted']
        total_net = frontend['total'] + backend['total'] + other['total']
        total_current = frontend['current'] + backend['current'] + other['current']
        
        print(f"{Fore.MAGENTA}{'总计':^66}")
        print(f"{Fore.MAGENTA}{'=' * 70}")
        print(f"  【累计工作量】")
        print(f"    新增行数：{Fore.GREEN}{Style.BRIGHT}{total_added:>10,}")
        print(f"    删除行数：{Fore.RED}{Style.BRIGHT}{total_deleted:>10,}")
        print(f"    净增行数：{Fore.CYAN}{Style.BRIGHT}{total_net:>10,}")
        if self.current_stats_available:
            print(f"  【当前代码量】")
            print(f"    当前拥有：{Fore.MAGENTA}{Style.BRIGHT}{total_current:>10,} 行")
        print()
        
        # 对比说明
        if self.current_stats_available and total_added > 0:
            work_ratio = (total_added / total_current * 100) if total_current > 0 else 0
            print(f"{Fore.CYAN}{'数据对比':^66}")
            print(f"{Fore.CYAN}{'-' * 70}")
            print(f"{Fore.WHITE}  💡 你累计写了 {Fore.GREEN}{Style.BRIGHT}{total_added:,}{Fore.WHITE} 行代码")
            print(f"{Fore.WHITE}  💡 当前代码库中有 {Fore.MAGENTA}{Style.BRIGHT}{total_current:,}{Fore.WHITE} 行是你的")
            if total_current > 0:
                print(f"{Fore.WHITE}  💡 工作效率比：{Fore.YELLOW}{Style.BRIGHT}{work_ratio:.1f}%{Fore.WHITE} （累计÷当前）")
                if work_ratio > 150:
                    print(f"{Fore.YELLOW}     → 说明：代码经历了较多的重构和优化（这是好事！）")
                elif work_ratio > 110:
                    print(f"{Fore.GREEN}     → 说明：代码质量稳定，适度重构")
                else:
                    print(f"{Fore.CYAN}     → 说明：代码一次成型，修改较少")
            print()
        
        print(f"{Fore.CYAN}{'=' * 70}\n")
    
    def print_top_files(self, top_n: int = 10):
        """
        打印修改最多的文件
        
        Args:
            top_n: 显示前 N 个文件
        """
        if not self.file_stats:
            return
        
        print(f"{Fore.CYAN}修改最多的 {top_n} 个文件：")
        print(f"{Fore.CYAN}{'-' * 70}")
        
        # 按净增行数排序
        sorted_files = sorted(
            self.file_stats.items(),
            key=lambda x: x[1]['added'] - x[1]['deleted'],
            reverse=True
        )[:top_n]
        
        for i, (file_path, stats) in enumerate(sorted_files, 1):
            net_change = stats['added'] - stats['deleted']
            print(f"{i:2}. {file_path}")
            if self.current_stats_available:
                print(f"    累计 - 新增：{Fore.GREEN}{stats['added']:>6}{Fore.RESET}  "
                      f"删除：{Fore.RED}{stats['deleted']:>6}{Fore.RESET}  "
                      f"净增：{Fore.CYAN}{net_change:>6}{Fore.RESET}")
                print(f"    当前 - 拥有：{Fore.MAGENTA}{stats['current']:>6}{Fore.RESET} 行")
            else:
                print(f"    新增：{Fore.GREEN}{stats['added']:>6}{Fore.RESET}  "
                      f"删除：{Fore.RED}{stats['deleted']:>6}{Fore.RESET}  "
                      f"净增：{Fore.CYAN}{net_change:>6}{Fore.RESET}")
        
        print()
    
    def export_html_report(self, output_path: str = None) -> str:
        """
        导出 HTML 报告
        
        Args:
            output_path: 输出路径（可选）
        
        Returns:
            保存的文件路径
        """
        generator = HTMLReportGenerator(
            repo_path=self.repo_path,
            user_name=self.git_user_name,
            user_email=self.git_user_email,
            branch=self.repo.active_branch.name
        )
        
        saved_path = generator.generate(self.stats, self.file_stats, output_path)
        return saved_path


def main():
    """主函数"""
    print(f"{Fore.CYAN}{Style.BRIGHT}")
    print("=" * 60)
    print("Git 代码行数统计工具".center(52))
    print("=" * 60)
    print(f"{Style.RESET_ALL}")
    
    # 获取仓库路径
    if len(sys.argv) > 1:
        repo_path = sys.argv[1]
    else:
        repo_path = input(f"{Fore.YELLOW}请输入 Git 仓库路径：{Fore.RESET}").strip()
        if not repo_path:
            print(f"{Fore.RED}错误：未提供仓库路径")
            sys.exit(1)
    
    # 检查路径是否存在
    if not os.path.exists(repo_path):
        print(f"{Fore.RED}错误：路径不存在：{repo_path}")
        sys.exit(1)
    
    try:
        # 创建统计器
        counter = GitCounter(repo_path)
        
        # 执行分析
        counter.analyze()
        
        # 打印报告
        counter.print_report()
        
        # 打印文件统计
        counter.print_top_files(top_n=10)
        
        # 询问是否导出 HTML 报告
        print(f"\n{Fore.CYAN}{'=' * 60}")
        export_choice = input(f"{Fore.YELLOW}是否导出 HTML 报告？(y/n): {Fore.RESET}").strip().lower()
        
        if export_choice in ['y', 'yes', 'Y']:
            try:
                html_path = counter.export_html_report()
                print(f"{Fore.GREEN}✓ HTML 报告已保存到: {html_path}")
                
                # 询问是否打开
                open_choice = input(f"{Fore.YELLOW}是否在浏览器中打开？(y/n): {Fore.RESET}").strip().lower()
                if open_choice in ['y', 'yes', 'Y']:
                    import webbrowser
                    webbrowser.open('file://' + os.path.abspath(html_path))
                    print(f"{Fore.GREEN}✓ 已在浏览器中打开报告")
            except Exception as e:
                print(f"{Fore.RED}✗ 导出 HTML 报告失败: {e}")
        
    except ValueError as e:
        print(f"{Fore.RED}{e}")
        sys.exit(1)
    except KeyboardInterrupt:
        print(f"\n{Fore.YELLOW}用户中断操作")
        sys.exit(0)
    except Exception as e:
        print(f"{Fore.RED}发生错误：{e}")
        import traceback
        traceback.print_exc()
        sys.exit(1)


if __name__ == '__main__':
    main()

